#!/usr/bin/python2.7

from mininet.cli import CLI
from mininet.net import Mininet
from mininet.node import RemoteController
from mininet.term import makeTerm

if '__main__' == __name__:
	net = Mininet(controller=RemoteController)

	# controllers
	c0 = net.addController('con0', port=6633)
	c1 = net.addController('con1', port=6634)

	L1 = 4
	L2 = L1 * 2
	L3 = L2
	c = []
	a = []
	e = []

	# add core ovs
	for i in range(L1):
		sw = net.addSwitch('c{}'.format(i + 1))
		c.append(sw)

	# add aggregation ovs
	for i in range(L2):
		sw = net.addSwitch('a{}'.format(L1 + i + 1))
		a.append(sw)

	# add edge ovs
	for i in range(L3):
		sw = net.addSwitch('e{}'.format(L1 + L2 + i + 1))
		e.append(sw)

	# add links between core and aggregation ovs
	for i in range(L1):
		sw1 = c[i]
		for sw2 in a[i/2::L1/2]:
			if str(sw1) == 'c1' and str(sw2) == 'a4': # link 2
				continue
			if str(sw1) == 'c1' and str(sw2) == 'a6': # link 4
				continue
			if str(sw1) == 'c2' and str(sw2) == 'a3': # link 5
				continue
			if str(sw1) == 'c2' and str(sw2) == 'a5': # link 7
				continue
			net.addLink(sw2, sw1)

	# add links between aggregation and edge ovs
	for i in range(0, L2, 2):
		for sw1 in a[i:i+2]:
			for sw2 in e[i:i+2]:
				if str(sw1) == 'a4' and str(sw2) == 'e8': # link 12
					continue
				if str(sw1) == 'a5' and str(sw2) == 'e10': # link 14
					continue
				net.addLink(sw2, sw1)

	#add hosts and its links with edge ovs
	count = 1
	for sw1 in e:
		host = net.addHost('h{}'.format(count),
						   mac='00:00:00:00:00:0{}'.format(count))
		net.addLink(sw1, host)
		count += 1

	net.build()

	c0.start()
	for s in c:
		s.start([c0])
	for s in a:
		s.start([c0])
	for s in e:
		s.start([c0, c1])

	net.startTerms()

	CLI(net)

	net.stop()

# > ryu-manager <app> --ofp-tcp-listen-port=<port>
